package com.flashcash.solu.view.camera.presenter;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.support.annotation.NonNull;
import android.util.Log;

import com.flashcash.solu.R;
import com.flashcash.solu.app.base.presenter.BaseActivityPresenterImpl;
import com.flashcash.solu.bean.PhotoInfo;
import com.flashcash.solu.utils.StringFormatUtils;
import com.flashcash.solu.widget.xleotoast.XLeoToast;
import com.hwangjr.rxbus.RxBus;
import com.flashcash.kotlin.data.FileType;
import com.x.leo.apphelper.log.XLog;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.SoftReference;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * @作者:My
 * @创建日期: 2017/6/21 12:14
 * @描述:${TODO}
 * @更新者:${Author}$
 * @更新时间:${Date}$
 * @更新描述:${TODO}
 */

public class TakePhotoActPreImp extends BaseActivityPresenterImpl implements TakePhotoActPresenter {

    private static final int PHOTO_FILE_SIZE_MAX = 2 * 1024 * 1024;
    final int BITMAP_MAX_SQUARE_SIZE = 3920;

    public void onTaken(byte[] data, FileType fileType) {
        Observable.create((Observable.OnSubscribe<PhotoInfo>) subscriber -> {
            try {

                SoftReference<Bitmap> rotated = getRotatedBitmap(getBitmapWithMaxLimit(data, BITMAP_MAX_SQUARE_SIZE, PHOTO_FILE_SIZE_MAX));

                File processedFile = StringFormatUtils.getFileByFileName(mView.getBaseActivity(), fileType.name() + ".jpg");
                saveBitmap(rotated.get(), processedFile, 80);
                //no need to recycle
//                fileSizeLimited.get().recycle();
//                rawBitmap.recycle();
//                rotated.get().recycle();

                PhotoInfo photoinfo = new PhotoInfo();
                photoinfo.fileType = fileType;
                photoinfo.mFile = processedFile;

                subscriber.onNext(photoinfo);

            } catch (Exception e) {
                XLog.INSTANCE.e("", e, 10);
                subscriber.onError(e);
            }

        }).observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.newThread())
                .subscribe(new Subscriber<PhotoInfo>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        XLeoToast.showMessage(mView.getBaseActivity().getString(R.string.show_generate_wrong));
                        if (isAttached()) {
                            mView.getBaseActivity().dismissLoading();
                            mView.getBaseActivity().finish();
                        }
                    }

                    @Override
                    public void onNext(PhotoInfo photoInfo) {
                        RxBus.get().post(photoInfo);
                        if (isAttached()) {
                            mView.getBaseActivity().dismissLoading();
                            mView.getBaseActivity().finish();
                        }
                    }
                });
    }

    private void saveBitmap(Bitmap bitmap, String fileName, int quality) throws IOException {

        File file = StringFormatUtils.getFileByFileName(mView.getBaseActivity(), fileName);

        if (file.exists()) {
            file.delete();
        }
        FileOutputStream out = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
        System.gc();
        out.flush();
        out.close();
    }

    private void saveBitmap(Bitmap bitmap, File file, int quality) throws IOException {

        if (file.exists()) {
            file.delete();
        }
        FileOutputStream out = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
        System.gc();
        out.flush();
        out.close();
    }

    private SoftReference<Bitmap> getRotatedBitmap(SoftReference<Bitmap> scaledBitmap){
        if (scaledBitmap.get() != null
                && scaledBitmap.get().getWidth() < scaledBitmap.get().getHeight()) {

            return rotateBitmap(scaledBitmap);
        } else {
            return scaledBitmap;
        }
    }
    //size w|h < 3920 && length < 2M
    private SoftReference<Bitmap> getBitmapWithMaxLimit(byte[] data, final int maxSquerSize, final int maxFileSize) {

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
        opts.inPurgeable = true;
        opts.inInputShareable = true;
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
        SoftReference<Bitmap> temp = new SoftReference<>(BitmapFactory.decodeStream(byteArrayInputStream, null, opts));

        SoftReference<Bitmap> result = temp;

        final float BITMAP_MAX_SQUARE_SIZE_FLOAT = maxSquerSize * 1.0f;

        if (temp.get().getWidth() > maxSquerSize || temp.get().getHeight() > maxSquerSize) {

            //缩小到框内
            float proportion = BITMAP_MAX_SQUARE_SIZE_FLOAT / Math.max(temp.get().getWidth(), temp.get().getHeight());

            int outWidth = ((int) (temp.get().getWidth() * proportion));
            int outHeight = ((int) (temp.get().getHeight() * proportion));

            result = new SoftReference<>(Bitmap.createScaledBitmap(temp.get(), outWidth, outHeight, true));
            Log.d("cameraxxx", "getBitmapWithMaxLimit result width:"+result.get().getWidth()+" getBitmapWithMaxLimit result height:"+result.get().getHeight());

            temp.clear();
        }

        if(data.length > maxFileSize){

            float proportion = 1.0f * maxFileSize / data.length;
            int width = (int) (result.get().getWidth() * proportion);
            int height = (int) (result.get().getHeight() * proportion);
            SoftReference<Bitmap> scaled = new SoftReference<>(Bitmap.createScaledBitmap(result.get(), width, height, false));
            Log.d("cameraxxx", "CompressedByFileSize width:"+scaled.get().getWidth()+" CompressedByFileSize height:"+scaled.get().getHeight());

            result.clear();
            return scaled;
        }

        return result;
    }

    //旋转图片-90度
    @NonNull
    private SoftReference<Bitmap> rotateBitmap(SoftReference<Bitmap> bitmap) {
        return rotateBitmap2(bitmap, 0 - 90);
    }

    @NonNull
    private Bitmap rotateBitmap(Bitmap bitmap, float degree) {
        XLog.INSTANCE.d("rotateBitmap:reSet", 10);
        Bitmap cameraBitmap = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getWidth(), Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(cameraBitmap);
        Matrix matrix = new Matrix();
        matrix.setTranslate(bitmap.getHeight() / 2 - bitmap.getWidth() / 2, bitmap.getWidth() / 2 - bitmap.getHeight() / 2);
        matrix.postRotate(degree, bitmap.getHeight() / 2, bitmap.getWidth() / 2);

        canvas.drawBitmap(bitmap, matrix, new Paint());
        XLog.INSTANCE.d("rotateBitmap:end", 10);
        return cameraBitmap;
    }

    //增加20M
    private SoftReference<Bitmap> rotateBitmap2(SoftReference<Bitmap> bitmap, float degree) {
        XLog.INSTANCE.d("rotateBitmap2:reSet", 10);
        Matrix m = new Matrix();
        m.setRotate(degree, bitmap.get().getWidth() / 2, bitmap.get().getHeight() / 2);
        SoftReference<Bitmap> bitmapSoftReference = new SoftReference<>(Bitmap.createBitmap(bitmap.get(), 0, 0, bitmap.get().getWidth(), bitmap.get().getHeight(), m, true));
//        bitmap.clear();
        XLog.INSTANCE.d("rotateBitmap2:end", 10);
        return bitmapSoftReference;
    }
}
